package com.zj.baseproxy.utils;

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;

/**
 * @author arthur_zhou
 */
public class LambdaUtil {

    private static final String GET_PREFIX = "get";

    @FunctionalInterface
    public interface IGetter<T> extends Serializable {
        /**
         * get方法 Class::getXXX
         *
         * @param t 对象
         * @return get方法返回值
         */
        Object get(T t);
    }

    /**
     * 获取属性名
     *
     * @param fn lambda表达式
     * @return get的字段名称
     */
    public static String getClassPropertiesName(IGetter<?> fn) {
        try {
            SerializedLambda lambda = getSerializedLambda(fn);
            String methodName = lambda.getImplMethodName();
            if (!methodName.startsWith(GET_PREFIX)) {
                throw new RuntimeException("无效的getter方法");
            }
            return camelToUnderscore(methodName.replace(GET_PREFIX, ""));
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("通过getter的方法引用获取字段名失败");
        }
    }

    /**
     * 获取序列化后的lambda表达式
     *
     * @param fnc lambda表达式
     * @return SerializedLambda
     */
    private static SerializedLambda getSerializedLambda(Serializable fnc) throws Exception {
        Method method = fnc.getClass().getDeclaredMethod("writeReplace");
        method.setAccessible(Boolean.TRUE);
        return (SerializedLambda) method.invoke(fnc);
    }

    /**
     * 驼峰转下划线
     *
     * @param field 驼峰字符串
     * @return 下划线字符串
     */
    public static String camelToUnderscore(String field) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < field.length(); i++) {
            char c = field.charAt(i);
            if (i > 0 && Character.isUpperCase(c)) {
                sb.append("_");
            }
            sb.append(Character.toLowerCase(c));
        }
        return sb.toString();
    }
}
